/*
 * @Author: secrets123
 * @Date: 2022-07-21 10:53:28
 * @LastEditors: error: error: git config user.name & please set dead value or install git && error: git config user.email & please set dead value or install git & please set dead value or install git
 * @LastEditTime: 2023-06-25 18:01:30
 * @FilePath: \stm32g431_AllRings\applications\soft_iic.c
 * @Description:
 *
 * Copyright (c) 2022 by secrets123 1097290967@qq.com, All Rights Reserved.
 */
#include <rtthread.h>
#include <rtconfig.h>
#include <board.h>
#include "soft_iic.h"

#define DBG_TAG "soft_iic"
#define DBG_LVL DBG_ERROR // DBG_INFO
#include <rtdbg.h>

/*Private define-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- */
#ifdef SCA_STM32G474MD
#define EE_SCL_PIN GPIO_PIN_8 // ģ��IIC��SCL�ź�  1.�޸����ż����޸�IIC�ӿ�
#define EE_SDA_PIN GPIO_PIN_9 // ģ��IIC��SDA�ź�
#define EE_I2C_GPIO GPIOC
#else
#define EE_SCL_PIN GPIO_PIN_9 // ģ��IIC��SCL�ź�  1.�޸����ż����޸�IIC�ӿ�
#define EE_SDA_PIN GPIO_PIN_8 // ģ��IIC��SDA�ź�
#define EE_I2C_GPIO GPIOA
#endif

#define EE_IIC_SCL(val) HAL_GPIO_WritePin(EE_I2C_GPIO, EE_SCL_PIN, val) // SCL
#define EE_IIC_SDA(val) HAL_GPIO_WritePin(EE_I2C_GPIO, EE_SDA_PIN, val) // SDA
/* Private macro -------------------------------------------------------------*/

/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/

void EE_SDA_IN(void) // ���ó�����
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    GPIO_InitStruct.Pin = EE_SDA_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(EE_I2C_GPIO, &GPIO_InitStruct);
}
void EE_SDA_OUT(void) // ���ó����
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    GPIO_InitStruct.Pin = EE_SDA_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(EE_I2C_GPIO, &GPIO_InitStruct);
}

void EE_SCK_OUT(void) // ���ó����
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    GPIO_InitStruct.Pin = EE_SCL_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(EE_I2C_GPIO, &GPIO_InitStruct);
}

unsigned char EE_READ_SDA(void)
{
    return HAL_GPIO_ReadPin(EE_I2C_GPIO, EE_SDA_PIN);
}

/******************************************************************************
 *��  ����void EE_IIC_Delay(void)
 *�����ܣ�IIC��ʱ
 *��  ������
 *����ֵ����
 *��  ע: ��ֲʱֻ��Ҫ��EE_IIC_Delay()�����Լ�����ʱ����
 *******************************************************************************/
void EE_IIC_Delay(uint8_t us)
{
    for (int i = 0; i < 180; i++)
    {
        __asm("NOP"); // core bus 160M  ����´��IIC���� 400K
    }
}
/******************************************************************************
 *��  ����void IIC_Init(void)
 *�����ܣ�IIC��ʼ��
 *��  ������
 *����ֵ����
 *��  ע����
 *******************************************************************************/

void EE_IIC_Init(void)
{
#ifdef SCA_STM32G474MD
    __HAL_RCC_GPIOC_CLK_ENABLE();
#else
    __HAL_RCC_GPIOA_CLK_ENABLE();
#endif

    EE_SCK_OUT();
    EE_SDA_OUT();
    EE_IIC_SCL(1);
    EE_IIC_SDA(1);
}
//INIT_BOARD_EXPORT(EE_IIC_Init);

void EE_IIC_Start(void)
{
    EE_SDA_OUT(); // sda�����
    EE_IIC_SDA(1);
    EE_IIC_SCL(1);
    EE_IIC_Delay(4);
    EE_IIC_SDA(0); // START:when CLK is high,DATA change form high to low
    EE_IIC_Delay(4);
    EE_IIC_SCL(0); // ǯסI2C���ߣ�׼�����ͻ��������
}

void EE_IIC_Stop(void)
{
    EE_SDA_OUT(); // sda�����
    EE_IIC_SCL(0);
    EE_IIC_SDA(0); // STOP:when CLK is high DATA change form low to high
    EE_IIC_Delay(4);
    EE_IIC_SCL(1);
    EE_IIC_SDA(1); // ����I2C���߽����ź�
    EE_IIC_Delay(4);
}

uint8_t EE_IIC_WaitAck(void)
{
    uint8_t ucErrTime = 0;
    EE_SDA_IN(); // SDA����Ϊ����  ���ӻ���һ���͵�ƽ��ΪӦ��
    EE_IIC_SDA(1);
    EE_IIC_Delay(1);
    EE_IIC_SCL(1);
    EE_IIC_Delay(1);
    ;
    while (EE_READ_SDA())
    {
        ucErrTime++;
        if (ucErrTime > 250)
        {

            EE_IIC_Stop();
            return 1;
        }
    }
    EE_IIC_SCL(0); // ʱ�����0
    return 0;
}

void EE_IIC_Ack(void)
{
    EE_IIC_SCL(0);
    EE_SDA_OUT();
    EE_IIC_SDA(0);
    EE_IIC_Delay(1);
    EE_IIC_SCL(1);
    EE_IIC_Delay(2);
    EE_IIC_SCL(0);
}

void EE_IIC_NAck(void)
{
    EE_IIC_SCL(0);
    EE_SDA_OUT();
    EE_IIC_SDA(1);
    EE_IIC_Delay(1);
    EE_IIC_SCL(1);
    EE_IIC_Delay(1);
    EE_IIC_SCL(0);
}

void EE_IIC_SendByte(uint8_t data)
{
    uint8_t t;
    EE_SDA_OUT();
    EE_IIC_SCL(0); // ����ʱ�ӿ�ʼ���ݴ���
    for (t = 0; t < 8; t++)
    {
        EE_IIC_SDA((data & 0x80) >> 7);
        EE_IIC_Delay(1);
        EE_IIC_SCL(1);
        data <<= 1;
        EE_IIC_Delay(1);
        EE_IIC_SCL(0);
    }
    EE_IIC_Delay(1);
}

uint8_t EE_IIC_ReadByte(uint8_t ack)
{
    uint8_t i, receive = 0;
    EE_SDA_IN(); // SDA����Ϊ����ģʽ �ȴ����մӻ���������
    for (i = 0; i < 8; i++)
    {
        EE_IIC_SCL(0);
        EE_IIC_Delay(1);
        EE_IIC_SCL(1);
        receive <<= 1;
        if (EE_READ_SDA())
            receive++; // �ӻ����͵ĵ�ƽ
        EE_IIC_Delay(1);
    }
    if (ack)
        EE_IIC_Ack(); // ����ACK
    else
        EE_IIC_NAck(); // ����nACK
    return receive;
}
